package net.ermannofranco.xml.schema;

import static net.ermannofranco.xml.schema.XmlType.ANYURI;
import static net.ermannofranco.xml.schema.XmlType.BASE_64_BIN;
import static net.ermannofranco.xml.schema.XmlType.BOOLEAN;
import static net.ermannofranco.xml.schema.XmlType.BYTE;
import static net.ermannofranco.xml.schema.XmlType.DATE;
import static net.ermannofranco.xml.schema.XmlType.DATETIME;
import static net.ermannofranco.xml.schema.XmlType.DECIMAL;
import static net.ermannofranco.xml.schema.XmlType.DOUBLE;
import static net.ermannofranco.xml.schema.XmlType.DURATION;
import static net.ermannofranco.xml.schema.XmlType.ENTITIES;
import static net.ermannofranco.xml.schema.XmlType.ENTITY;
import static net.ermannofranco.xml.schema.XmlType.FLOAT;
import static net.ermannofranco.xml.schema.XmlType.GREG_DAY;
import static net.ermannofranco.xml.schema.XmlType.GREG_MONTH;
import static net.ermannofranco.xml.schema.XmlType.GREG_MONTHDAY;
import static net.ermannofranco.xml.schema.XmlType.GREG_YEAR;
import static net.ermannofranco.xml.schema.XmlType.GREG_YEARMONTH;
import static net.ermannofranco.xml.schema.XmlType.HEXB;
import static net.ermannofranco.xml.schema.XmlType.ID;
import static net.ermannofranco.xml.schema.XmlType.IDREF;
import static net.ermannofranco.xml.schema.XmlType.IDREFS;
import static net.ermannofranco.xml.schema.XmlType.INT;
import static net.ermannofranco.xml.schema.XmlType.INTEGER;
import static net.ermannofranco.xml.schema.XmlType.LANGUAGE;
import static net.ermannofranco.xml.schema.XmlType.LONG;
import static net.ermannofranco.xml.schema.XmlType.NAME;
import static net.ermannofranco.xml.schema.XmlType.NCNAME;
import static net.ermannofranco.xml.schema.XmlType.NEG_INTEGER;
import static net.ermannofranco.xml.schema.XmlType.NMTOKEN;
import static net.ermannofranco.xml.schema.XmlType.NMTOKENS;
import static net.ermannofranco.xml.schema.XmlType.NON_NEG_INTEGER;
import static net.ermannofranco.xml.schema.XmlType.NON_POS_INTEGER;
import static net.ermannofranco.xml.schema.XmlType.NORMAL_STRING;
import static net.ermannofranco.xml.schema.XmlType.NOTATION;
import static net.ermannofranco.xml.schema.XmlType.POS_INTEGER;
import static net.ermannofranco.xml.schema.XmlType.QNAME;
import static net.ermannofranco.xml.schema.XmlType.SHORT;
import static net.ermannofranco.xml.schema.XmlType.STRING;
import static net.ermannofranco.xml.schema.XmlType.TIME;
import static net.ermannofranco.xml.schema.XmlType.TOKEN;
import static net.ermannofranco.xml.schema.XmlType.UNSIGNED_BYTE;
import static net.ermannofranco.xml.schema.XmlType.UNSIGNED_INT;
import static net.ermannofranco.xml.schema.XmlType.UNSIGNED_LONG;
import static net.ermannofranco.xml.schema.XmlType.UNSIGNED_SHORT;
import net.ermannofranco.xml.ArraySupport;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class FacetUtils {

	private final static Log log = LogFactory.getLog(FacetUtils.class);

	private FacetUtils() {
	}

	private static final ArraySupport<XmlType> chainer = ArraySupport
			.factory(XmlType.class);
	public static final XmlType[] primitive = { STRING, BOOLEAN, DECIMAL,
			FLOAT, DOUBLE, DURATION, DATETIME, TIME, DATE, GREG_YEARMONTH,
			GREG_YEAR, GREG_MONTHDAY, GREG_MONTH, GREG_DAY, HEXB, BASE_64_BIN,
			ANYURI, QNAME, NOTATION };
	public static final XmlType[] derivedDecimal = { INTEGER, NON_NEG_INTEGER,
			LONG, NON_POS_INTEGER, POS_INTEGER, NEG_INTEGER, INT,
			UNSIGNED_LONG, SHORT, BYTE, UNSIGNED_INT, UNSIGNED_SHORT,
			UNSIGNED_BYTE };
	public static final XmlType[] derivedString = { NORMAL_STRING, TOKEN,
			LANGUAGE, NAME, NMTOKEN, NCNAME, NMTOKENS, ID, IDREF, ENTITY,
			IDREFS, ENTITIES };
	
	public static final XmlType[] vEnumerationBASE = { ANYURI, BASE_64_BIN,
			DATE, DATETIME, DECIMAL, DOUBLE, DURATION, FLOAT, GREG_DAY,
			GREG_MONTH, GREG_MONTHDAY, GREG_YEAR, GREG_YEARMONTH, HEXB,
			NOTATION, QNAME, STRING, TIME };
	public static final XmlType[] vAllBASE = { BOOLEAN, ANYURI, BASE_64_BIN,
			DATE, DATETIME, DECIMAL, DOUBLE, DURATION, FLOAT, GREG_DAY,
			GREG_MONTH, GREG_MONTHDAY, GREG_YEAR, GREG_YEARMONTH, HEXB,
			NOTATION, QNAME, STRING, TIME };
	public static final XmlType[] vBoundBASE = { DATE, DATETIME, DECIMAL,
			DOUBLE, DURATION, FLOAT, GREG_DAY, GREG_MONTH, GREG_MONTHDAY,
			GREG_YEAR, GREG_YEARMONTH, TIME };
	public static final XmlType[] vLengthBASE = { ANYURI, BASE_64_BIN, HEXB,
			NOTATION, QNAME, STRING };
	public static final XmlType[] vDigitsBASE = { DECIMAL };

	public static final XmlType[] vAll = chainer.concat(vAllBASE,
			derivedString, derivedDecimal).toArray(new XmlType[0]);
	// { BOOLEAN, ANYURI, BASE_64_BIN, DATE,
	// DATETIME, DECIMAL, DOUBLE, DURATION, FLOAT, GREG_DAY, GREG_MONTH,
	// GREG_MONTHDAY, GREG_YEAR, GREG_YEARMONTH, HEXB, NOTATION, QNAME,
	// STRING, TIME, NORMAL_STRING, TOKEN, LANGUAGE, NAME, NMTOKEN,
	// NCNAME, NMTOKENS, ID, IDREF, ENTITY, IDREFS, ENTITIES };

	public static final XmlType[] vEnumeration = chainer.concat(
			vEnumerationBASE, derivedString, derivedDecimal).toArray(
			new XmlType[0]);
	// { ANYURI, BASE_64_BIN, DATE,
	// DATETIME, DECIMAL, DOUBLE, DURATION, FLOAT, GREG_DAY, GREG_MONTH,
	// GREG_MONTHDAY, GREG_YEAR, GREG_YEARMONTH, HEXB, NOTATION, QNAME,
	// STRING, TIME, NORMAL_STRING, TOKEN, LANGUAGE, NAME, NMTOKEN,
	// NCNAME, NMTOKENS, ID, IDREF, ENTITY, IDREFS, ENTITIES };
	
	public static final XmlType[] vBound = chainer.concat(vBoundBASE,
			derivedDecimal).toArray(new XmlType[0]);
	// { DATE, DATETIME, DECIMAL, DOUBLE,
	// DURATION, FLOAT, GREG_DAY, GREG_MONTH, GREG_MONTHDAY, GREG_YEAR,
	// GREG_YEARMONTH, TIME, INTEGER, NON_NEG_INTEGER, LONG,
	// NON_POS_INTEGER, POS_INTEGER, NEG_INTEGER, INT, UNSIGNED_LONG,
	// SHORT, BYTE, UNSIGNED_INT, UNSIGNED_SHORT, UNSIGNED_BYTE };
	
	public static final XmlType[] vDigits = chainer.concat(vDigitsBASE,
			derivedDecimal).toArray(new XmlType[0]);
	// { DECIMAL, INTEGER,
	// NON_NEG_INTEGER, LONG, NON_POS_INTEGER, POS_INTEGER, NEG_INTEGER,
	// INT, UNSIGNED_LONG, SHORT, BYTE, UNSIGNED_INT, UNSIGNED_SHORT,
	// UNSIGNED_BYTE };
	
	public static final XmlType[] vLength = chainer.concat(vLengthBASE,
			derivedString).toArray(new XmlType[0]);

	// { ANYURI, BASE_64_BIN, HEXB,
	// NOTATION, QNAME, STRING, NORMAL_STRING, TOKEN, LANGUAGE, NAME,
	// NMTOKEN, NCNAME, NMTOKENS, ID, IDREF, ENTITY, IDREFS, ENTITIES };

	public static boolean validate(Facet facetType, XmlType[] typeArray,
			XmlType... typeNumber) {
		// System.out.println("typeNumber: " + typeNumber);
		// CORRETTO PER TIPI DERIVATI 18 APR 2004
		// if (typeNumber<0) throw new
		// SchemaException(Facet.getName(facetType)+" non permesso con i Facet.");//tipi
		// derivati non permessi?

		// if (typeNumber==null) return true;

		outer: for (int i = 0; i < typeNumber.length; i++) {
			for (int j = 0; j < typeArray.length; j++) {
				XmlType proof = typeArray[j];
				XmlType proved = typeNumber[i];
				log.debug("validating " + facetType + ": " + proof + " vs "
						+ proved);
				if (proof == proved) {
					log.debug("validation " + facetType + ": " + proof + " vs "
							+ proved + ": OK");
					continue outer;
				}
			}
			throw new SchemaException(Facet.getName(facetType)
					+ " non permesso con " + XmlType.getType(typeNumber[i]));
		}
		return true;
	}
}
